﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Security.AccessControl;
using System.Text;

namespace Mrsoft.Update.Common
{
    public static class StreamExtense
    {
        /// <summary>
        /// 将字节数组完全写入流中
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="buffer"></param>
        public static void Write(this Stream stream, byte[] buffer)
        {
            stream.Write(buffer, 0, buffer.Length);
        }

        /// <summary>
        /// 将文本写入流中
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="message"></param>
        public static void Write(this Stream stream, string message)
        {
            stream.Write(Encoding.ASCII.GetBytes(message));
        }

        /// <summary>
        /// 以Format的方式来构建文本写入流
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="message">模块文本</param>
        /// <param name="extraMessage">参数信息</param>
        public static void Write(this Stream stream, string message, params  object[] extraMessage)
        {
            stream.Write(string.Format(message, extraMessage));
        }

        /// <summary>
        /// 从网络流中获取返回数据
        /// </summary>
        /// <param name="ns"></param>
        /// <param name="ms"></param>
        /// <returns></returns>
        public static Encoding GetResponse(this NetworkStream ns, Stream ms)
        {
            ns.ReadTimeout = 10000;
            //遇到第一个“\r\n\r\n”就返回
            long length = 0;
            var encoding = Encoding.UTF8;
            #region 获取http响应头
            var f1 = '\r';
            var f2 = '\n';
            var buffer = new byte[1];
            var fi = 0;
            var hs = new MemoryStream(0x1000);
            while (true)
            {
                ns.Read(buffer, 0, 1);
                fi = (buffer[0] == f1 || buffer[0] == f2) ? (++fi) : 0;
                hs.WriteByte(buffer[0]);
                if (fi > 3)
                {
                    break;
                }
            }
            #endregion

            #region 分析响应头并且解析出正文长度
            var headerArr = Encoding.ASCII.GetString(hs.ToArray()).Split(new string[] { "\r\n" }, StringSplitOptions.None);
            //用于存放header信息
            if (headerArr.Length > 0)
            {
                var headers = new Dictionary<string, string>();
                //var header = headerArr[0];
                //var first = header.IndexOf(' ');
                //var second = header.IndexOf(' ', first + 1);
                ////分析第一个
                //var http = header.Substring(0, first);//因为first对应的是空格所以不算在内
                //var status = header.Substring(first + 1, second - (first + 1));
                //var statusStr = header.Substring(second + 1);
                //Console.WriteLine("HTTP：{0}\r\nstatuscode:{1}statuString:{2}aaaa", http, status, statusStr);
                //开始分析下面的
                for (int i = 1; i < headerArr.Length; i++)
                {
                    var str = headerArr[i];
                    var temArr = str.Split(':');
                    if (temArr.Length == 2 )
                    {
                        if(headers.Keys.Contains(temArr[0]))
                        {
                            headers[temArr[0]] += ";" + temArr[1];
                        }
                        else if (temArr[0] == "Content-Type")
                        {
                            var more = temArr[1].Split(';');
                            headers.Add(temArr[0], more[0]);
                            if (more.Length > 1)
                            {
                                more = more[1].Split('=');
                                headers.Add(more[0].Trim(), more[1]);
                                if (more[0] == "charset")
                                    encoding = Encoding.GetEncoding(more[1]);
                            }
                        }
                        else
                        {
                            headers.Add(temArr[0], temArr[1]);
                        }
                    }
                }
                string contentLengthString;
                if (headers.TryGetValue("Content-Length", out contentLengthString))
                {
                    long.TryParse(contentLengthString.Trim(), out length);
                }
                //foreach (KeyValuePair<string, string> kv in headers)
                //{
                //    Console.WriteLine("{0}:{1}",kv.Key,kv.Value);
                    
                //}
            }
            hs.Close();



            //---------------
            #endregion

            if (length == 0)
            {
                #region 从响应头获取长度失败之后直接从正文获取长度
                hs = new MemoryStream(128);
                while (true)
                {
                    ns.Read(buffer, 0, 1);
                    fi = (buffer[0] == f1 || buffer[0] == f2) ? (++fi) : 0;
                    hs.WriteByte(buffer[0]);
                    if (fi > 1)
                    {
                        break;
                    }
                }
                string str = Encoding.UTF8.GetString(hs.ToArray()).Replace("\r\n", "");
                //Console.WriteLine("从响应头获取到数据长度文本为{0}", str);
                try
                {
                    length = Convert.ToInt64(str, 16);
                    //length = length - hs.Length;
                    //Console.WriteLine("从正文获取到数据长度为{0}", length);
                }
                catch
                {
                }
                hs.Close();
                #endregion
            }

            #region 接收数据
            //Console.WriteLine("数据长度为{0}", length);
            ms = ms ?? new MemoryStream();
            buffer = new byte[10240];//创建一个10K的buffer
            while (length > 0)
            {
                var recv = ns.Read(buffer, 0, buffer.Length);
                ms.Write(buffer, 0, recv);
                length -= recv;
            }
            #endregion
            return encoding;
        }       
    }
}
